const http = require('http')
const query = require('querystring');
const fs = require('fs')
const path = require('path')
const BufferHelper = require('bufferhelper')

module.exports = async (ctx, next) => {
  const url = ctx.request.url
  // console.log('request.body----------', ctx.request.body)
  if (url.indexOf('api/') !== -1) {
    try {
      let key = url.split('/')[2]
      let port = ''
      let cofig_path = path.join(__dirname, '../modules.config.json')
      let confg_modules = JSON.parse(fs.readFileSync(cofig_path))
      let exist_server = false
      confg_modules.map((c) => {
        if(c.key === key) {
          port = c.port
          exist_server = true
        }
      })
      if (exist_server) {
        let prox = await httpRequest(ctx, {port: port})
        // 设置相应头
        const str = JSON.stringify(prox.head)
        // console.log('prox.head', str)
        for (let key in prox.head) {
          if (key.toString() === 'connection') {
            ctx.set(key, 'keep-alive')
          } else {
            if (key.toString() !== 'transfer-encoding') {
              ctx.set(key, prox.head[key])
            }
          }
        }
        ctx.set('content-length', '255')
        // console.log('prox.header', prox.head)
        // ctx.response.headers = prox.head
        if (prox.head.location) {
          ctx.response.redirect('/home')
        } else {
          ctx.response.body = prox.body
        }
        // console.log('ctx.response.headers', ctx.response.headers)
        // console.log('ctx.response.body', ctx.response.body)
      } else {
        ctx.body = '无效的api'
      }
    } catch (err) {
      console.log(err)
    }
  } else {
    await next()
  }
}

const httpRequest = (ctx, opts) => {
  return new Promise((resolve) => {
      delete ctx.request.header.port;
      const options = {
          port: opts.port,
          path: ctx.request.url,
          method: ctx.request.method,
          headers: ctx.request.header
      }
      let requestBody={},
          body,
          head,
          chunks = [],
          fileFields,
          files,
          boundaryKey,
          boundary,
          endData,
          filesLength,
          totallength = 0;
      if (ctx.request.body && JSON.stringify(ctx.request.body) !== "{}") {
          if (ctx.request.header['content-type'].indexOf('application/x-www-form-urlencoded') > -1) {
            console.log('application/x-www-form-urlencoded')
              requestBody = ctx.request.body.toString()
              requestBody = JSON.stringify(requestBody)
              options.headers['Content-Length'] = Buffer.byteLength(requestBody)
          } else if (ctx.request.header['content-type'].indexOf('application/json') > -1) {
            console.log('application/json')
              requestBody = JSON.stringify(ctx.request.body);
              options.headers['Content-Length'] = Buffer.byteLength(requestBody)
          } else if (ctx.request.header['content-type'].indexOf('multipart/form-data') > -1) {
              fileFields = ctx.request.body.fields;
              files = ctx.request.body.files;
              boundaryKey = Math.random().toString(16);
              boundary = `\r\n----${boundaryKey}\r\n`;
              endData = `\r\n----${boundaryKey}--`;
              filesLength = 0;

              Object.keys(fileFields).forEach((key) => {
                  requestBody +=  `${boundary}Content-Disposition:form-data;name="${key}"\r\n\r\n${fileFields[key]}`;
              })

              Object.keys(files).forEach((key) => {
                  requestBody += `${boundary}Content-Type: application/octet-stream\r\nContent-Disposition: form-data; name="${key}";filename="${files[key].name}"\r\nContent-Transfer-Encoding: binary\r\n\r\n`;
                  filesLength += Buffer.byteLength(requestBody,'utf-8') + files[key].size;
              })

              options.headers['Content-Type'] = `multipart/form-data; boundary=--${boundaryKey}`;
              options.headers[`Content-Length`] = filesLength + Buffer.byteLength(endData);
          }
      } else {
          requestBody = JSON.stringify(ctx.request.body)
          options.headers['Content-Length'] = Buffer.byteLength(requestBody)
      }
      let req
      let bufferhelper = new BufferHelper()
      try {
        req = http.request(options, (res) => {
          res.on('data', (chunk) => {
            // let decoder = new StringDecoder('utf8')
            bufferhelper.concat(chunk)
            // console.log(chunk)
            //   chunks.push(chunk);
            //   totallength += chunk.length;
          })
          res.on('error', (e) => {
            console.log(e)
          })
          res.on('end', () => {
            // console.log(bufferhelper.toBuffer().toString())
              // body = JSON.parse(Buffer.concat(chunks, totallength).toString())
              body = bufferhelper.toBuffer().toString()
              // console.log('--------------------', body)
              head = res.headers
              resolve({head, body});
          })
        })
        ctx.request.body && req.write(requestBody);
      } catch (err) {
        console.log(err)
      }
      

      if (fileFields) {
          let filesArr = Object.keys(files);
          let uploadConnt = 0;
          filesArr.forEach((key) => {
              let fileStream = fs.createReadStream(files[key].path);
              fileStream.on('end', () => {
                  fs.unlink(files[key].path);
                  uploadConnt++;
                  if (uploadConnt == filesArr.length) {
                      req.end(endData)
                  }
              })
              fileStream.pipe(req, {end: false})
          })
      } else {
          req.end();
      }

  })
}
